import service
import collections
import geo2
import blue

class SelectionClientComponent():
    __guid__ = 'entity.SelectionClientComponent'
    ALWAYS_ACCEPT_MODE = 1
    ALWAYS_REJECT_MODE = 2
    MAX_DISTANCE_MODE = 3

    def __init__(self):
        self.modeEnum = SelectionClientComponent.MAX_DISTANCE_MODE
        self.maxSelectionDistance = 10




class SelectionClient(service.Service):
    __guid__ = 'svc.selectionClient'
    __notifyevents__ = []
    __componentTypes__ = ['selectionComponent']

    def Run(self, *etc):
        self.mouseInputService = sm.GetService('mouseInput')
        self.neocom = sm.GetService('neocom')
        self.defaultSelectionComponent = SelectionClientComponent()
        self.selectedEntityID = None
        self.InitModeToMethodDict()
        self.mouseInputService.RegisterCallback(const.INPUT_TYPE_MOUSEDOWN, self.OnMouseDown)
        self.renderableToEntity = {}



    def InitModeToMethodDict(self):
        self.modeToMethodDict = {SelectionClientComponent.ALWAYS_ACCEPT_MODE: self._TryAlwaysAcceptMode,
         SelectionClientComponent.ALWAYS_REJECT_MODE: self._TryAlwaysRejectMode,
         SelectionClientComponent.MAX_DISTANCE_MODE: self._TryMaxDistanceMode}



    def CreateComponent(self, name, state):
        component = SelectionClientComponent()
        if state:
            component.__dict__.update(state)
        return component



    def ReportState(self, component):
        report = collections.OrderedDict(sorted(component.__dict__.items()))
        return report



    def RegisterComponent(self, entity, component):
        if entity.HasComponent('graphic'):
            graphicComponent = entity.GetComponent('graphic')
            if graphicComponent.renderObject:
                self.RegisterRenderableWithEntityID(graphicComponent.renderObject, entity.entityID)
        if entity.HasComponent('paperdoll'):
            paperDollComponent = entity.GetComponent('paperdoll')
            self.RegisterRenderableWithEntityID(paperDollComponent.doll.avatar, entity.entityID)



    def UnRegisterComponent(self, entity, component):
        if entity.HasComponent('graphic'):
            graphicComponent = entity.GetComponent('graphic')
            self.RegisterRenderableWithEntityID(graphicComponent.renderObject, None)
        if entity.HasComponent('paperdoll'):
            paperDollComponent = entity.GetComponent('paperdoll')
            self.RegisterRenderableWithEntityID(paperDollComponent.doll.avatar, None)



    def _TryAlwaysAcceptMode(self, selectionComponent, pickedEntity):
        return True



    def _TryAlwaysRejectMode(self, selectionComponent, pickedEntity):
        return False



    def _TryMaxDistanceMode(self, selectionComponent, pickedEntity):
        pickedPos = pickedEntity.GetComponent('position').position
        playerPos = self.entityService.GetPlayerEntity().GetComponent('position').position
        distSq = geo2.Vec3DistanceSq(pickedPos, playerPos)
        maxDist = selectionComponent.maxSelectionDistance
        maxSq = (maxDist * maxDist)
        return (distSq <= maxSq)



    def RegisterRenderableWithEntityID(self, renderable, entityID):
        id = blue.GetID(renderable)
        if ((entityID is None) and (id in self.renderableToEntity)):
            del self.renderableToEntity[id]
        else:
            self.renderableToEntity[id] = entityID



    def GetSelectedEntityID(self):
        return self.selectedEntityID



    def FindEntityByRenderable(self, renderable):
        if (renderable is None):
            return 
        else:
            id = blue.GetID(renderable)
            return self.renderableToEntity.get(id, None)



    def TrySelect(self, entityID):
        pickedEntity = self.entityService.FindEntityByID(entityID)
        if not pickedEntity:
            return 
        else:
            if pickedEntity.HasComponent('selection'):
                selectionComponent = pickedEntity.GetComponent['selection']
            else:
                return 
            methodToCall = self.modeToMethodDict[selectionComponent.modeEnum]
            selectionAccepted = methodToCall(selectionComponent, pickedEntity)
            self.selectedEntityID = (entityID if selectionAccepted else None)
            self.neocom.UpdateLocationText()
            return selectionAccepted



    def OnMouseDown(self, button, posX, posY, entityID):
        if entityID:
            self.TrySelect(entityID)




